package persistence;

import persistence.database.DatabasePersistenceFactory;
import persistence.serialization.SerializePersistenceFactory;

public class DataPersistor {
	private static DataPersistor _instance;
	private TransactionManager _transactionMgr;
	private DataPersistenceFactory _factory;
	/**
	 * Retrieve the one and only Data Persistor
	 * @return the DataPersistor
	 */
	static public DataPersistor instance(){
		if (_instance == null)
			_instance = new DataPersistor();
		return _instance;
	}
	
	/**
	 * Initialize the DataPersistor class with the current mode of 
	 * saving (this allows DataPersistor to determine the correct
	 * concrete factory). This method will also load the initial model.
	 * @param mode
	 * @throws Exception For a loading error, or a bad mode string
	 */
	public void init(String mode) throws Exception{
		_transactionMgr = null;
		if (mode.equals("-serial")) {
			System.err.println("Running in serial mode");
			_factory = new SerializePersistenceFactory();
		}
		else if (mode.equals("-db")) {
			System.err.println("Running in database mode");
			_factory = new DatabasePersistenceFactory();
		}
		else
			throw new IllegalArgumentException("Expected -serial or -db to determine saving " +
					"strategy");
		
		getTransactionManager().beginTransaction();
		_factory.getAllDAO().load();
		getTransactionManager().endTransaction(true);
		
	}
	
	/**
	 * Return a concrete DataPersistenceFactory
	 * @return a concrete DataPersistenceFactory
	 */
	public DataPersistenceFactory getFactory(){
		assert(_factory != null);
		return _factory;
	}
	
	/**
	 * Return THE Transaction Manager.
	 * @return THE Transaction Manager.
	 * @pre init must have already been called (getFactory() != null)
	 */
	public TransactionManager getTransactionManager(){
		assert(_factory != null);
		if (_transactionMgr == null)
			_transactionMgr = _factory.getTransactionManager();
		return _transactionMgr;
	}
	
	/**
	 * Return an instance of an ItemDAO.
	 * @return an ItemDAO
	 * @pre init must have already been called (getFactory() != null)
	 */
	public ItemDAO getItemDAO(){
		assert(_factory != null);
		return _factory.getItemDAO();
	}
	
	/**
	 * Return an instance of a ProductDAO
	 * @return a ProductDAO
	 * @pre init must have already been called (getFactory() != null)
	 */
	public ProductDAO getProductDAO(){
		assert(_factory != null);
		return _factory.getProductDAO();
	}
	
	/**
	 * Return an instance of a ContainerDAO
	 * @return a ContainerDAO
	 * @pre init must have already been called (getFactory() != null)
	 */
	public ContainerDAO getContainerDAO(){
		assert(_factory != null);
		return _factory.getContainerDAO();
	}
	
	/**
	 * Return an instance of a ProductContainerDAO
	 * @return a ProductContainerDAO
	 * @pre init must have already been called (getFactory() != null)
	 */
	public ProductContainerDAO getProductContainerDAO(){
		assert(_factory != null);
		return _factory.getProductContainerDAO();
	}
	
	/**
	 * Return an instance of an AllDAO
	 * @return an AllDAO
	 * @pre init must have already been called (getFactory() != null)
	 */
	public AllDAO getAllDAO(){
		assert(_factory != null);
		return _factory.getAllDAO();
	}
	
	
	/**
	 * Return an instance of a ReportDAO
	 * @return a ReportDAO
	 * @pre init must have already been called (getFactory() != null)
	 */
	public ReportDAO getReportDAO(){
		assert(_factory != null);
		return _factory.getReportDAO();
	}
	
	/**
	 * The private constructor
	 */
	private DataPersistor(){
		
	}

}
